Promise.race = function (arr) {
  const Constructor = this; // this 是调用 race 的 Promise 构造器函数。
  if (!Array.isArray(arr)) {
    return new Constructor(function (_, reject) {
      return reject(new TypeError('You must pass an array to race.'));
    });
  }
  return new Constructor((resolve, reject) => {
    arr.forEach((promise) => {
      Constructor.resolve(promise) //这是为了防止参数并非Promise处理的
        .then(resolve, reject);
    });
  });
};

Promise.all = function (arr) {
  const Constructor = this;
  if (!Array.isArray(arr)) {
    return Constructor.reject(new TypeError('You must pass an array to all.'));
  }
  let counter = arr.length;
  if (counter === 0) {
    return Constructor.resolve(arr);
  }
  return new Constructor((resolve, reject) => {
    const result = [];
    arr.forEach((promise, i) => {
      Constructor.resolve(promise) //这是为了防止参数并非Promise处理的
        .then((val) => {
          result[i] = val;
          counter--;
          if (counter === 0) {
            resolve(result);
          }
        }, reject);
    });
  });
};

a = function () {
  return new Promise((resolve => {
    setTimeout(function () {
      resolve(20);
    }, 0);
  }));
};

b = function () {
  return new Promise((resolve => {
    setTimeout(function () {
      resolve(200);
    }, 1000);
  }));
};

c = function () {
  return new Promise((resolve, reject) => {
    setTimeout(function () {
      // reject('error');
      resolve(1000);
    }, 1000);
  });
};

// Promise.race([a(), b()]).then(function (data) {
//   console.log(data);
// });

// Promise.all([a(), b(), c()]).then(function (data) {
//   console.log(data);
// }).catch(console.error);

Promise.prototype.done = function (onFullfilled, onRejected) {
  this.then(onFullfilled, onRejected).catch((err) => {
    setTimeout(() => {
      throw err
    });
  });
};

Promise.prototype.finally = function (callback) {
  let P = this.constructor;
  return this.then(
    (data) => P.resolve(callback()).then(() => data),
    (err) => P.resolve(callback()).catch(() => { throw err }));
};

// (async function () {
//   // c().finally(()=> {
//   //   console.log('done');
//   // });
//   b().then(function () {
//     // throw new Error('-----')
//     return Promise.reject('haha')
//   });
// })();

//any和all刚好相反，有一个成功就返回成功，如果全部失败，才会返回所有失败信息。与race也不一样，race只要有一个成功或失败都返回。
Promise.any2 = function (arr) {
  const Constructor = this; // this 是调用 race 的 Promise 构造器函数。
  if (!Array.isArray(arr)) {
    return Constructor.reject(new TypeError('You must pass an array to any.'));
  }
  return new Constructor((resolve, reject) => {
    const errors = [];
    let counter = arr.length;
    if (counter === 0) { //如果一个都没有，则返回失败
      return reject(errors);
    }
    arr.forEach((promise, i) => {
      Promise.resolve(promise).then(resolve, (err) => {
        counter--;
        errors[i] = err;
        if (counter === 0) {
          // rejects(new AggregateError(errors));
          reject(errors);
        }
      });
    });
  });
};

// console.log(Promise.any2([123]))
(async function () {
  console.time('app');
  // await Promise.all([a(), b(), c()])
  // for await (var p of [a(), b(), c()]) {
  for (var p of [b(), a(), c()]) {
    await p;
  }
  console.timeEnd('app');
})();
